#ifndef IMMERSED_OBJECT_WRITER_H
#define IMMERSED_OBJECT_WRITER_H

#include <vector>
#include <fstream>
#include <string>

#include "Properties.h"

template<typename T, template<typename U> class ImmersedObject>
class ImmersedObjectWriter
{
public:

	ImmersedObjectWriter();

	~ImmersedObjectWriter();

	ImmersedObjectWriter(const ImmersedObjectWriter& rhs);

	ImmersedObjectWriter clone();

public:

	static ImmersedObjectWriter* IOWriterFactory();

	void writeObjects();

	void BeginWriteObjects(const std::string& fileName, std::vector< ImmersedObject<T> >& objectChain, unsigned nDim);

	void EndWriteObjects(const std::string& fileName, std::vector< ImmersedObject<T> >& objectChain, unsigned nDim);

	void writeDataArray(ImmersedObjectProperties property, std::vector< ImmersedObject<T> >& objectChain, const std::string& name, T scalingFactor, int nDim);

private:





private:

	std::ofstream fileStream;

};

template<typename T, template< typename U> class ImmersedObject>
ImmersedObjectWriter<T, ImmersedObject>::~ImmersedObjectWriter()
{

}

template<typename T, template< typename U> class ImmersedObject>
ImmersedObjectWriter<T, ImmersedObject> ImmersedObjectWriter<T, ImmersedObject>::clone()
{
	return ImmersedObjectWriter<T, ImmersedObject>(*this);
}

#ifndef PARALLEL_MODE_MPI
template<typename T, template< typename U> class ImmersedObject>
ImmersedObjectWriter<T, ImmersedObject>::ImmersedObjectWriter()
{

}
#endif

template<typename T, template< typename U> class ImmersedObject>
ImmersedObjectWriter<T, ImmersedObject>::ImmersedObjectWriter()
{

}

template<typename T, template< typename U> class ImmersedObject>
void ImmersedObjectWriter<T, ImmersedObject>::BeginWriteObjects(const std::string& fileName, std::vector< ImmersedObject<T> >& objectChain, unsigned nDim)
{
	fileStream.open(fileName.c_str(), std::ios_base::out);

	fileStream << "<?xml version=\"1.0\"?>" << std::endl;
	fileStream << "<VTKFile type=\"UnstructuredGrid\" version=\"0.1\" byte_order=\"LittleEndian\">" << std::endl;
	fileStream << "\t<UnstructuredGrid>" << std::endl;
	fileStream << "\t\t<Piece NumberOfPoints=\"" << objectChain.size() << "\" NumberOfCells=\"0\">" << std::endl;
	fileStream << "\t\t\t<PointData Scalars=\"Radius\">" << std::endl;
}

template<typename T, template< typename U> class ImmersedObject>
void ImmersedObjectWriter<T, ImmersedObject>::EndWriteObjects(const std::string& fileName, std::vector< ImmersedObject<T> >& objectChain, unsigned nDim)
{
	fileStream << "\t\t\t</PointData>" << std::endl;

	fileStream << "\t\t\t<Points>" << std::endl;
	fileStream << "\t\t\t\t<DataArray type=\"Float32\" NumberOfComponents=\"3\" format=\"ascii\">" << std::endl;

	for(unsigned objectIndex = 0; objectIndex != objectChain.size(); ++objectIndex)
		for(unsigned dimIndex = 0; dimIndex != nDim; ++dimIndex)
			fileStream << objectChain[objectIndex].getPosition()[dimIndex] << " ";

	fileStream << std::endl;
	fileStream << "\t\t\t\t</DataArray>" << std::endl;
	fileStream << "\t\t\t</Points>" << std::endl;
	fileStream << "\t\t\t<Cells>" << std::endl;
	fileStream << "\t\t\t\t<DataArray type=\"UInt8\" Name=\"types\" format=\"ascii\">" << std::endl;
	fileStream << "\t\t\t\t</DataArray>" << std::endl;
	fileStream << "\t\t\t</Cells>" << std::endl;
	fileStream << "\t\t</Piece>" << std::endl;
	fileStream << "\t</UnstructuredGrid>" << std::endl;
	fileStream << "</VTKFile>" << std::endl;

	fileStream.close();
	fileStream.clear();
}

template<typename T, template< typename U> class ImmersedObject>
void ImmersedObjectWriter<T, ImmersedObject>::writeDataArray(ImmersedObjectProperties property, std::vector< ImmersedObject<T> >& objectChain, const std::string& name, T scalingFactor, int nDim)
{
	if(objectChain.size() == 0)
		return;

	if(objectChain.size() == 1)
	{
		fileStream << "\t\t\t\t<DataArray type=\"Float64\" Name=\"" << name << "\" format=\"ascii\">" << std::endl;
	}
	else
	{
		fileStream << "\t\t\t\t<DataArray type=\"Float64\" Name=\"" << name << "\" NumberOfComponents=\""
				   << objectChain.size()
				   << "\" format=\"ascii\">" << std::endl;
	}

	for(unsigned objectIndex = 0; objectIndex != objectChain.size(); ++objectIndex)
	{
		for(unsigned dimIndex = 0; dimIndex != nDim; ++dimIndex)
			fileStream << objectChain[objectIndex].getFluidEffect(property)[dimIndex] << " ";
	}

	fileStream << std::endl;
	fileStream << "\t\t\t\t</DataArray>" << std::endl;
}

#endif // IMMERSED_OBJECT_WRITER_H
